#include "ahufsm.h"
#include "ahudata.h"
#include "ahutimer.h"

extern ahu_dev_t *ahu_dev_hd;
extern int	mq_id;

/* 状态机的初始态所对应的几种转移 */
ahu_fsmtrans_t fsm_init[] = {
    {EV_SYS_START,  &ahu_fsmpre_null,           &fsm_init_2sf_onwait,   &ahu_fsmend_null,   S_SF_ONWAIT},
};

/* 状态机的风机开等待态所对应的几种转移 */
ahu_fsmtrans_t fsm_sf_onwait[] = {
    {EV_SF_ON,      &fsm_sf_onwait_2idle_pre,   &fsm_sf_onwait_2idle,   &ahu_fsmend_null,   S_IDLE},
    {EV_SYS_STOP,   &fsm_sf_onwait_2init_pre,   &fsm_sf_onwait_2init,   &ahu_fsmend_null,   S_INIT},
};

/* 状态机的空闲态对应的几种转移 */
ahu_fsmtrans_t fsm_idle[] = {
    {EV_SYS_STOP,   &ahu_fsmpre_null,           &fsm_idle_2init,        &ahu_fsmend_null,   S_INIT},
};

/* 状态机集合 */
ahu_fsmsets_t ahu_fsmset[] = {
    {"S_INIT",          sizeof(fsm_init)/sizeof(fsm_init[0]),           fsm_init},
    {"S_SF_ONWAIT",     sizeof(fsm_sf_onwait)/sizeof(fsm_sf_onwait[0]), fsm_sf_onwait},
    {"S_IDLE",          sizeof(fsm_idle)/sizeof(fsm_idle[0]),           fsm_idle},
};

enum error_code ahu_fsmpre_null(void *arg)
{
    return Success;
}

enum error_code ahu_fsmaction_null(void *arg)
{
    return Success;
}

enum error_code ahu_fsmend_null(void *arg)
{
    return Success;
}

/* 预处理删除定时器 */
enum error_code fsm_init_2init_pre(void *arg)
{
    es_timer_del(((ahu_dev_t *)arg)->tmr_sf_offwait);
    return Success;
}

/* 由初始态转移到风机开等待处理函数 */
enum error_code fsm_init_2sf_onwait(void *arg)
{
    data_type_u val;

    /* 打开风机 */
    val.b = true;
    set_cmdpoint_ifexist("SF-C", (ahu_dev_t *)arg, val, TypeOfVal_BOOL);
    /* TODO: 变频 */

    /* 根据device_id组合定时器名字 */
    combine_string(((ahu_dev_t *)arg)->tmr_sf_onwait, TMR_SF_ONWAIT, ((ahu_dev_t *)arg)->device_id);
    /* 添加一个定时器，到时后判断风机状态 */
    es_timer_add(((ahu_dev_t *)arg)->tmr_sf_onwait, TMO_SF_ONWAIT, TMO_SF_ONWAIT, ahu_to_sf_onwait, arg);
    return Success;
}

enum error_code fsm_sf_onwait_2idle_pre(void *arg)
{
    es_timer_del(((ahu_dev_t *)arg)->tmr_sf_onwait);
    return Success;
}

enum error_code fsm_sf_onwait_2init_pre(void *arg)
{
    es_timer_del(((ahu_dev_t *)arg)->tmr_sf_onwait);
    return Success;
}

enum error_code fsm_sf_onwait_2idle(void *arg)
{
    data_type_u val;

    /* 1 新风阀 */
        /* 1.1 开关型 */
        val.b = true;
        set_cmdpoint_ifexist("OAD-C", (ahu_dev_t *)arg, val, TypeOfVal_BOOL);

        /* 1.2 调节型 */
        val.d = 10.0;
        set_cmdpoint_ifexist("OAD-TC", (ahu_dev_t *)arg, val, TypeOfVal_DOUBLE);

    /* 2. 回风阀 */
        /* 2.1 开关型 */
        val.b = true;
        set_cmdpoint_ifexist("RAD-C", (ahu_dev_t *)arg, val, TypeOfVal_BOOL);

        /* 2.2 调节型 */
        val.d = 90.0;   // 新风阀+回风阀 = 100.0%
        set_cmdpoint_ifexist("RAD-TC", (ahu_dev_t *)arg, val, TypeOfVal_DOUBLE);

    return Success;
}

enum error_code fsm_sf_onwait_2init(void *arg)
{
    data_type_u val;

    /* close 风机 */
    val.b = false;
    set_cmdpoint_ifexist("SF-C", (ahu_dev_t *)arg, val, TypeOfVal_BOOL);
    //TODO: 变频怎么关

    return Success;
}

enum error_code fsm_idle_2init(void *arg)
{
    data_type_u val;

    /* close 风机 */
    val.b = false;
    set_cmdpoint_ifexist("SF-C", (ahu_dev_t *)arg, val, TypeOfVal_BOOL);
    //TODO: 变频怎么关

    /* close 新风阀 */
        /* 1.1 开关型 */
        val.b = false;
        set_cmdpoint_ifexist("OAD-C", (ahu_dev_t *)arg, val, TypeOfVal_BOOL);

        /* 1.2 调节型 */
        val.d = 0.0;
        set_cmdpoint_ifexist("OAD-TC", (ahu_dev_t *)arg, val, TypeOfVal_DOUBLE);

    /* close 回风阀 */
        /* 2.1 开关型 */
        val.b = false;
        set_cmdpoint_ifexist("RAD-C", (ahu_dev_t *)arg, val, TypeOfVal_BOOL);

        /* 2.2 调节型 */
        val.d = 0.0;
        set_cmdpoint_ifexist("RAD-TC", (ahu_dev_t *)arg, val, TypeOfVal_DOUBLE);

    return Success;
}

/* 状态机
 * @evt: 收到的事件
 * @ahu_dev：设备
 */
void fsm_do(ahu_ev_tp_e evt, ahu_dev_t *ahu_dev)
{
    printf("fsm do %s \n", ahu_dev->device_id);

    int i;
    /* 所有状态的状态集合 */
    ahu_fsmsets_t *fsmset = ahu_dev->fsm.fsmset;
    /* 找到当前状态下的状态转移集合 */
    ahu_fsmtrans_t *fsmtrans = fsmset[ahu_dev->fsm.cur_state].ahu_fsm;
    /* 找到当前状态下有几个事件分支 */
    int	ret = fsmset[ahu_dev->fsm.cur_state].num;

    for(i=0; i<ret; i++){
		if(evt == (int)fsmtrans[i].event){
			break;
		}
	}

    if(i>=ret){

    }else{
        /* 1 预处理 */
        ret = (*fsmtrans[i].pre)(ahu_dev);
        /* 1.1 预处理成功 */
        if(ret == Success){
            /* 2 执行 */
            ret = (*fsmtrans[i].action)(ahu_dev);
            /* 2.1 执行成功 */
            if(ret == Success){
                /* 2.1.1 切换状态 */
                ahu_dev->fsm.pre_state = ahu_dev->fsm.cur_state;
                ahu_dev->fsm.cur_state = fsmtrans[i].next_state;
                /* 3 收尾 */
                ret = (*fsmtrans[i].end)(ahu_dev);
                /* 3.1 收尾失败 */
                if(ret != Success){
                    ES_PRT_ERROR("AHU: dev_id[%s] fsm end error: goto status[%s], event[%d] \n", ahu_dev->device_id, fsmset[ahu_dev->fsm.cur_state].name, ahu_dev->fsm.fsmevt);
                }else{
                    ES_PRT_INFO("AHU: dev_id[%s] fsm from state[%s] to state[%s] \n", ahu_dev->device_id, fsmset[ahu_dev->fsm.pre_state].name, fsmset[ahu_dev->fsm.cur_state].name);
                }
            /* 2.2 执行失败, 状态不变 */
            }else{
                ES_PRT_ERROR("AHU: dev_id[%s] fsm action error: cur status[%s], event[%d] \n", ahu_dev->device_id, fsmset[ahu_dev->fsm.cur_state].name, ahu_dev->fsm.fsmevt);
            }

        /* 1.2 预处理失败，状态不变 */
        }else{
            ES_PRT_WARN("AHU:dev_id[%s] fsm stay old status[%s], event[%d] \n", ahu_dev->device_id, fsmset[ahu_dev->fsm.cur_state].name, ahu_dev->fsm.fsmevt);
        }
    }
}

/* 发送事件@evt到指定的设备@ahu_dev */
void send_event(ahu_dev_t *ahu_dev, ahu_ev_tp_e evt)
{
    ahu_msg_t tx_msg;
    tx_msg.mtype = AHU_MQTP_EVENT;
    tx_msg.fsmevt = evt;
    strcpy(tx_msg.device_id, ahu_dev->device_id);

    ES_PRT_INFO("send event[%d] to dev_id[%s] \n", evt, ahu_dev->device_id);
    if( msgsnd(mq_id, (void*)&tx_msg, sizeof(tx_msg)-sizeof(tx_msg.mtype), 0) < 0){
        ES_PRT_ERROR("%s, mtpye = %d, event = %d, dev_id = %s \n", strerror(errno), AHU_MQTP_EVENT, evt, ahu_dev->device_id);
    }
}

/* 检查每个设备的启停，发送启动或者停是事件 */
void ck_c_call_state()
{
    data_type_u val;

    ahu_dev_t *ahu_pos;

    /* 遍历每个设备 */
    list_for_each_entry(ahu_pos, &ahu_dev_hd->list, list){
        /* SF-ENA点位必须存在 */
        read_vp_byname(ahu_pos, "SF-ENA", &val);

        /* 启停点位的value和老value比对，有变化就发送事件 */
        if(ahu_pos->old_st_startup == false && val.b == true){
            send_event(ahu_pos, EV_SYS_START);

        }else if(ahu_pos->old_st_startup == true && val.b == false){
            send_event(ahu_pos, EV_SYS_STOP);
        }
        ahu_pos->old_st_startup = val.b;
    }

}

/* 轮询检查和状态相关的点位, 根据不同情况发送不同事件 */
void *ahu_state_ck_thread(void *arg)
{
    pthread_detach(pthread_self());

    while(1){
        sleep(2);
        /* 等待有设备被添加 */
        if(list_empty(&ahu_dev_hd->list) == 1){
            continue;
        }
        /* 检查每个设备的启停 */
        ck_c_call_state();
    }

    return NULL;
}